import mxgraph from './index';
import _ from 'lodash';
const {
  mxGraph,
  mxVertexHandler,
  mxConstants,
  mxCellState,
  mxPerimeter,
  mxCellEditor,
  mxGraphHandler,
  mxEvent,
  mxEdgeHandler,
  mxShape,
  mxEdgeStyle,
  mxConnectionConstraint,
  mxPoint,
  mxEventObject,
  mxRectangleShape,
  mxClipboard,
  mxCodec,
  mxObjectCodec,
  mxUtils,
  mxRubberband,
  mxImageExport,
  mxXmlCanvas2D,
  mxCodecRegistry,
  mxKeyHandler,
  mxUndoManager
} = mxgraph;

export class Graph extends mxGraph {

  constructor(container) {
    super(container);
    this._init();
  }

  _init() {
    this._setDefaultConfig();
    this._putVertexStyle();
    this._setDefaultEdgeStyle();
  }

  _setDefaultConfig() {
    // 编辑时按 escape 后完成输入
    mxCellEditor.prototype.escapeCancelsEditing = false;
    // 失焦时完成输入
    mxCellEditor.prototype.blurEnabled = true;
    // 线不允许拖动
    mxGraph.prototype.isCellMovable = function(cell) {
      if (cell) {
        if (cell.isVertex()) {
          if (cell.value.tagName == "Step")
            return true;
          else return false
        }
      }
    };
    // 去锯齿效果
    mxRectangleShape.prototype.crisp = true;
    // 拖拽过程对齐线
    mxGraphHandler.prototype.guidesEnabled = true;
    //禁用浏览器自带右击菜单
    mxEvent.disableContextMenu(this.container);
    // 禁止从将label从线条上拖离
    mxGraph.prototype.edgeLabelsMovable = false;
    // 是否连接线
    this.setConnectable(true);
    // 固定节点大小
    this.setCellsResizable(false);
    // 编辑时按回车键不换行，而是完成输入
    this.setEnterStopsCellEditing(true);
    // 禁止节点折叠
    this.foldingEnabled = false;
    // 文本包裹效果必须开启此配置
    this.setHtmlLabels(true);
    // 禁止游离线条
    this.setDisconnectOnMove(false);
    // 禁止连接线晃动
    this.setAllowDanglingEdges(false);
    // 允许调整线条弯曲度
    this.setCellsBendable(false);
    //节点是否提示
    this.setTooltips(true);
    // 允许连线的目标和源是同一元素
    this.setAllowLoops(false);
    // 右键移动容器坐标轴
    this.setPanning(true);
    // 允许拖动
    this.setDropEnabled(true);
    // 设置自动扩大鼠标悬停
    this.popupMenuHandler.autoExpand = true;
    //禁止重复连接
    this.setMultigraph(false);
    // 鼠标框选
    new mxRubberband(this);

    this.convertValueToString = function(cell) {
      const label = cell.getAttribute('label');
      return label;
    };
  }

  _putVertexStyle() {
    const normalTypeStyle = {
      [mxConstants.STYLE_SHAPE]: mxConstants.SHAPE_IMAGE,
      [mxConstants.STYLE_PERIMETER]: mxPerimeter.RectanglePerimeter,
    };
    this.getStylesheet().putCellStyle('normalType', normalTypeStyle);

    const nodeStyle = {
      [mxConstants.STYLE_SHAPE]: mxConstants.SHAPE_LABEL,
      [mxConstants.STYLE_PERIMETER]: mxPerimeter.RectanglePerimeter,
      [mxConstants.STYLE_ROUNDED]: true,
      [mxConstants.STYLE_ARCSIZE]: 10,

      [mxConstants.STYLE_STROKECOLOR]: '#3D6480',
      [mxConstants.STYLE_FONTCOLOR]: '#606266',
      [mxConstants.STYLE_FILLCOLOR]: '#FFFFFF',

      [mxConstants.STYLE_LABEL_BACKGROUNDCOLOR]: 'none',

      [mxConstants.STYLE_ALIGN]: mxConstants.ALIGN_CENTER,
      [mxConstants.STYLE_VERTICAL_ALIGN]: mxConstants.ALIGN_TOP,
      [mxConstants.STYLE_IMAGE_ALIGN]: mxConstants.ALIGN_CENTER,
      [mxConstants.STYLE_IMAGE_VERTICAL_ALIGN]: mxConstants.ALIGN_TOP,

      [mxConstants.STYLE_IMAGE_WIDTH]: '32',
      [mxConstants.STYLE_IMAGE_HEIGHT]: '32',
      [mxConstants.STYLE_SPACING_TOP]: '50',
      [mxConstants.STYLE_SPACING]: '0',
    };
    this.getStylesheet().putCellStyle('node', nodeStyle);

    // 设置选中状态节点的边角为圆角，默认是直角
    const oldCreateSelectionShape = mxVertexHandler.prototype.createSelectionShape;
    mxVertexHandler.prototype.createSelectionShape = function createSelectionShape(...args) {
      const res = oldCreateSelectionShape.apply(this, args);
      res.isRounded = true;
      res.style = {
        arcSize: 0,
      };
      return res;
    };
  }

   _setDefaultEdgeStyle() {
      const style = this.getStylesheet().getDefaultEdgeStyle();
      Object.assign(style, {
        [mxConstants.STYLE_ROUNDED]: true, // 设置线条拐弯处为圆角
        [mxConstants.STYLE_STROKEWIDTH]: '1.3',
        [mxConstants.STYLE_STROKECOLOR]: '#3D6480',
        [mxConstants.STYLE_EDGE]: mxConstants.EDGESTYLE_ORTHOGONAL,
        [mxConstants.STYLE_FONTCOLOR]: '#3D6480',
        [mxConstants.STYLE_LABEL_BACKGROUNDCOLOR]: '#ffa94d',
      });
      // 设置拖拽线的过程出现折线，默认为直线
      this.connectionHandler.createEdgeState = () => {
        const edge = this.createEdge();
        return new mxCellState(this.view, edge, this.getCellStyle(edge));
      };
    }


  importModelXML(xmlTxt, x, y, src) {
    let cell;
    let doc = mxUtils.parseXml(xmlTxt);
    let root = doc.documentElement;
    graph.getModel().beginUpdate();
    try {
      cell = graph.insertVertex(graph.getDefaultParent(), null, root, x, y, 40, 40, "node;image=" + src);
      graph.setSelectionCells([cell]);
    } finally {
      graph.getModel().endUpdate();
    }
    return cell;
  }

  _getExportModel() {
    const model = _.cloneDeep(this.getModel());
    Object.values(model.cells)
      .forEach(cell => {
        if (cell.vertex && cell.data) {
          cell.data = JSON.stringify(cell.data);
        }
      });
    return model;
  }

  exportModelXML() {
    const enc = new mxCodec(mxUtils.createXmlDocument());
    const node = enc.encode(this._getExportModel());
    return mxUtils.getPrettyXml(node);
  }
}

let graph = null;

export const destroyGraph = () => {
  if (graph)
    graph.destroy();
  graph = null;
};

export const genGraph = (container) => {
  graph = new Graph(container);
  return graph;
};

export const getGraph = () => graph;
